
package com.kugou.game.sdk.ui.widget;

import com.kugou.framework.base.BaseBroadcastReceiver;
import com.kugou.game.sdk.api.common.User;
import com.kugou.game.sdk.core.FolderManager;
import com.kugou.game.sdk.core.SDKActions;
import com.kugou.game.sdk.core.SDKControler;
import com.kugou.game.sdk.core.UserManager;
import com.kugou.game.sdk.core.VipManager;
import com.kugou.game.sdk.protocol.FloatViewActivityLabelTask;
import com.kugou.game.sdk.protocol.FloatViewActivityLabelTask.FloatViewActivityLabelResponse;
import com.kugou.game.sdk.utils.AppUtil;
import com.kugou.game.sdk.utils.AsyncImageLoader;
import com.kugou.game.sdk.utils.AsyncImageLoader.ImageCallback;
import com.kugou.game.sdk.utils.Rx;
import com.kugou.game.sdk.utils.ThreadTaskManager;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.GridView;
import android.widget.ImageView;

import java.util.ArrayList;

/**
 * 描述:悬浮窗
 *
 * @author jerryliu
 * @since 2016年1月16日 下午5:40:18
 */
public class FloatView {
    private static final int SIDE_LEFT = -1;

    private static final int SIDE_RIGHT = -2;

    /** 显示位置：左上 */
    public static final int LEFT_TOP = 1;

    /** 显示位置：左中 */
    public static final int LEFT_MID = 2;

    /** 显示位置：左下 */
    public static final int LEFT_BOTTOM = 3;

    /** 显示位置：右上 */
    public static final int RIGHT_TOP = 4;

    /** 显示位置：右中 */
    public static final int RIGHT_MID = 5;

    /** 显示位置：右下 */
    public static final int RIGHT_BOTTOM = 6;

    private int position;

    // 悬浮窗左右边
    private int side;

    private Activity context;

    private GridView floatViewContentGrid;

    private ImageView floatViewIndicatorImage, floatViewIndicatorLabel;

    private View floatViewIndicatorLayout, floatViewContentLayout;

    private WindowManager wm;

    private WindowManager.LayoutParams lpIndicator, lpContent;

    private static FloatView fv;

    private int screenWidth, screenHeight, stateHeight, touchSlop;

    private int floatViewContentWidth, floatViewContentHeight, floatViewIndicatorWidth,
            floatViewIndicatorHeight;

    private boolean isAdd = false;

    private FloatViewContentAdapter adapter;

    private FloatViewReceiver receiver;

    private AsyncImageLoader loader;

    private FloatView(Activity activity, int position) {
        this.context = activity;
        // 初始悬浮窗位置
        if (position > 0 && position <= RIGHT_BOTTOM) {
            this.position = position;
        } else {
            this.position = LEFT_MID;
        }
        initToolbarReceiver();
        initParams();
        initViews(activity);
        initData();
        initPosition();
        // 设置悬浮窗背景
        setFloatViewIndicatorBackground();
        loader = new AsyncImageLoader();
        // 检查活动标签信息
        checkActivityLabelInfo();

    }

    private Handler mHandler = new Handler(Looper.getMainLooper());

    /** 检查活动标签信息 */
    private void checkActivityLabelInfo() {
        ThreadTaskManager.excuteTask(new Runnable() {
            @Override
            public void run() {
                FloatViewActivityLabelTask task = new FloatViewActivityLabelTask();
                FloatViewActivityLabelResponse response = task.request();
                if (response != null && response.isOk()) {
                    String iconUrl = response.getLableImageUrl();
                    String imgKey = iconUrl;
                    String savePath = FolderManager.IMAGE_CACHE_FOLDER
                            + AppUtil.getFileNameFromUrl(iconUrl);
                    Bitmap bitmap = loader.loadImage(context, imgKey, iconUrl, savePath,
                            new ImageCallback() {
                                @Override
                                public void imageLoaded(Bitmap bitmap, String key) {
                                    showActivityLabel(bitmap);
                                }
                            });

                    showActivityLabel(bitmap);
                }
            }
        });
    }

    protected void showActivityLabel(final Bitmap bitmap) {
        if (bitmap != null && floatViewIndicatorLabel != null) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    floatViewIndicatorLabel.setImageBitmap(bitmap);
                    if (adapter != null) {
                        adapter.showActivityTag(bitmap);
                    }
                }
            });
        }
    }

    public static FloatView getInstance(Activity activity) {
        return getInstance(activity, LEFT_MID);
    }

    public static FloatView getInstance(Activity activity, int position) {
        if (fv == null) {
            synchronized (FloatView.class) {
                if (fv == null) {
                    fv = new FloatView(activity, position);
                }
            }
        }
        return fv;
    }

    private void initToolbarReceiver() {
        receiver = new FloatViewReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(SDKActions.ACTION_UPDATE_TOOLBAR_AFTER_LOGIN_SUCCESS);
        filter.addAction(SDKActions.ACTION_SET_LOGIN_PSD_SUCCESS);
        filter.addAction(SDKActions.ACTION_CHANGE_TO_VIP);
        filter.addAction(SDKActions.ACTION_UNREAD_EMAIL_CLICKED);
        filter.addAction(SDKActions.ACTION_STATE_HAS_GIFTBAG);
        context.registerReceiver(receiver, filter);
    }

    private void initViews(Activity activity) {
        // 悬浮图标
        floatViewIndicatorLayout = LayoutInflater.from(activity).inflate(
                Rx.layout.kg_floatview_indicator, null);
        floatViewIndicatorImage = (ImageView) floatViewIndicatorLayout
                .findViewById(Rx.id.kg_tb_indicator_iv);
        floatViewIndicatorLabel = (ImageView) floatViewIndicatorLayout
                .findViewById(Rx.id.kg_tb_indicator_label);
        // 悬浮展开内容
        floatViewContentLayout = LayoutInflater.from(activity).inflate(
                Rx.layout.kg_floatview_content, null);
        floatViewContentGrid = (GridView) floatViewContentLayout
                .findViewById(Rx.id.kg_tb_content_grid);

        // 获取初始宽高
        ViewTreeObserver contentObserver = floatViewContentLayout.getViewTreeObserver();
        contentObserver.addOnPreDrawListener(new OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (floatViewContentLayout == null) {
                    return false;
                }
                floatViewContentLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                floatViewContentWidth = floatViewContentLayout.getWidth();
                floatViewContentHeight = floatViewContentLayout.getHeight();
                Log.d("dax", "onPreDraw:floatViewContentLayout:" + floatViewContentWidth + "--"
                        + floatViewContentHeight);
                initPosition();
                return true;
            }
        });

        ViewTreeObserver indicatorObserver = floatViewIndicatorLayout.getViewTreeObserver();
        indicatorObserver.addOnPreDrawListener(new OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (floatViewIndicatorLayout == null) {
                    return false;
                }
                floatViewIndicatorLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                floatViewIndicatorWidth = floatViewIndicatorLayout.getWidth();
                floatViewIndicatorHeight = floatViewIndicatorLayout.getHeight();

                initPosition();
                updateFloatView();
                floatViewContentLayout.setVisibility(View.GONE);
                Log.d("dax", "onPreDraw:floatViewIndicatorLayout:" + floatViewIndicatorWidth + "--"
                        + floatViewIndicatorHeight);
                return true;
            }
        });

        try {
            if (Build.VERSION.SDK_INT >= 11) {
                floatViewContentLayout.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                    @Override
                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
                        if (floatViewContentHeight != floatViewContentLayout.getHeight()
                                || floatViewContentWidth != floatViewContentLayout.getWidth()) {
                            floatViewContentWidth = floatViewContentLayout.getWidth();
                            floatViewContentHeight = floatViewContentLayout.getHeight();
                            updateFloatViewContentPosition();
                            updateFloatView();
                            Log.d("dax", "onLayoutChange:floatViewContentLayout:"
                                    + floatViewContentWidth + "--" + floatViewContentHeight);
                        }
                    }
                });
                floatViewIndicatorLayout.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                    @Override
                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
                        if (floatViewIndicatorHeight != floatViewIndicatorLayout.getHeight()
                                || floatViewIndicatorWidth != floatViewIndicatorLayout.getWidth()) {
                            floatViewIndicatorWidth = floatViewIndicatorLayout.getWidth();
                            floatViewIndicatorHeight = floatViewIndicatorLayout.getHeight();
                            updateFloatViewContentPosition();
                            updateFloatView();
                            Log.d("dax", "onLayoutChange:floatViewIndicatorLayout:"
                                    + floatViewIndicatorWidth + "--" + floatViewIndicatorHeight);
                        }
                    }
                });
            }
        } catch (Exception e) {
        }

        // 当点击悬浮窗以外区域时，收缩悬浮窗
        floatViewContentLayout.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_OUTSIDE:
                        if (!isInZone(floatViewContentLayout, (int) event.getRawX(),
                                (int) event.getRawY())) {
                            // 延时收缩悬浮窗，避免干扰主线程操作
                            ThreadTaskManager.excuteTask(new Runnable() {
                                @Override
                                public void run() {
                                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            closeFloatView();
                                        };
                                    }, 20);
                                }
                            });
                        }
                        return true;
                }
                return false;
            }
        });

        // 设置悬浮窗触摸监听
        floatViewIndicatorImage.setOnTouchListener(indicatorTouchListener);
    }

    private static final String TITLE_USERCENTER = "用户中心";

    private static final String TITLE_GAMECENTER = "游戏中心";

    private static final String TITLE_FORUM = "公告板";

    private static final String TITLE_GIFTBAG = "礼包";

    private static final String TITLE_SETPSD = "补填密码";

    private static final String TITLE_VIP = "VIP专属";

    private void initData() {
        User user = UserManager.getInstance().getCurrentUserInternal();
        ArrayList<BarInfo> data = new ArrayList<BarInfo>();
        // 用户中心
        BarInfo info = new BarInfo();
        info.iconResId = Rx.drawable.kg_selector_floatview_usercenter;
        info.title = TITLE_USERCENTER;
        info.index = FloatViewContentAdapter.INDEX_USERCENTER;
        data.add(info);

        // 游戏中心
        if (!SDKControler.isNeedHideGameCenter()) {
            BarInfo info1 = new BarInfo();
            info1.iconResId = Rx.drawable.kg_selector_floatview_gamecenter;
            info1.title = TITLE_GAMECENTER;
            info1.index = FloatViewContentAdapter.INDEX_GAMECENTER;
            data.add(info1);
        }

        // 论坛
        BarInfo info2 = new BarInfo();
        info2.iconResId = Rx.drawable.kg_selector_floatview_forum;
        info2.title = TITLE_FORUM;
        info2.index = FloatViewContentAdapter.INDEX_FORUM;
        data.add(info2);

        // 礼包
        if (user != null && user.isHasGift()) {
            BarInfo info3 = new BarInfo();
            info3.iconResId = Rx.drawable.kg_selector_floatview_giftbag;
            info3.title = TITLE_GIFTBAG;
            info3.index = FloatViewContentAdapter.INDEX_GIFTBAG;
            data.add(info3);
        }

        // 补填密码
        if (user != null && !user.isSetKugouPsd()) {
            BarInfo info4 = new BarInfo();
            info4.iconResId = Rx.drawable.kg_selector_floatview_setpsd;
            info4.title = TITLE_SETPSD;
            info4.index = FloatViewContentAdapter.INDEX_SETPSD;
            data.add(info4);
        }

        // 如果是VIP则添加显示入口
        if (VipManager.getInstance().isVip()) {
            BarInfo info5 = new BarInfo();
            info5.iconResId = Rx.drawable.kg_selector_floatview_vip;
            info5.title = TITLE_VIP;
            info5.index = FloatViewContentAdapter.INDEX_VIP;
            data.add(info5);
        }

        adapter = new FloatViewContentAdapter(context, data);
        // 添加红点显示
        if (user != null) {
            if (user.getUnreadmails() > 0 && !user.isUnreadMailReminded()) {
                adapter.addShowRedPoint(String.valueOf(FloatViewContentAdapter.INDEX_USERCENTER));
                startBreatheAnimation();
            } else if (user.isGameCenterNeedRedPointRemind()) {
                adapter.addShowRedPoint(String.valueOf(FloatViewContentAdapter.INDEX_GAMECENTER));
                startBreatheAnimation();
            } else if (!user.isSetKugouPsd()) {
                adapter.addShowRedPoint(String.valueOf(FloatViewContentAdapter.INDEX_SETPSD));
                startBreatheAnimation();
            }
        }
        floatViewContentGrid.setAdapter(adapter);
    }

    /** 显示VIP入口 */
    public synchronized void setVipVisible() {
        if (adapter != null && !adapter.isVisible(FloatViewContentAdapter.INDEX_VIP)) {
            BarInfo info5 = new BarInfo();
            info5.iconResId = Rx.drawable.kg_selector_floatview_vip;
            info5.title = TITLE_VIP;
            info5.index = FloatViewContentAdapter.INDEX_VIP;
            adapter.addData(info5);
            adapter.notifyDataSetChanged();
        }
    }

    /** 显示礼包入口 */
    public synchronized void setGiftBagVisible() {
        if (adapter != null && !adapter.isVisible(FloatViewContentAdapter.INDEX_GIFTBAG)) {
            BarInfo info3 = new BarInfo();
            info3.iconResId = Rx.drawable.kg_selector_floatview_giftbag;
            info3.title = TITLE_GIFTBAG;
            info3.index = FloatViewContentAdapter.INDEX_GIFTBAG;
            adapter.addData(2, info3);
            adapter.notifyDataSetChanged();
        }
    }

    /**
     * 判断触摸点是否在控件范围之内
     * 
     * @param view 参考控件
     * @param x 触摸点x
     * @param y 触摸点y
     * @return
     */
    public static boolean isInZone(View view, int x, int y) {
        if (null == view) {
            return false;
        }
        Rect mChangeImageBackgroundRect = new Rect();
        view.getDrawingRect(mChangeImageBackgroundRect);

        int[] location = new int[2];
        view.getLocationOnScreen(location);
        mChangeImageBackgroundRect.right = mChangeImageBackgroundRect.right
                - mChangeImageBackgroundRect.left + location[0];
        mChangeImageBackgroundRect.bottom = mChangeImageBackgroundRect.bottom
                - mChangeImageBackgroundRect.top + location[1];
        mChangeImageBackgroundRect.left = location[0];
        mChangeImageBackgroundRect.top = location[1];

        return mChangeImageBackgroundRect.contains(x, y);
    }

    private void initParams() {
        wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metric = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metric);
        screenWidth = metric.widthPixels;
        screenHeight = metric.heightPixels;
        stateHeight = AppUtil.getStateHeight(context);
        touchSlop = (int) (10 * metric.density);

        lpIndicator = new WindowManager.LayoutParams();
        lpIndicator.type = WindowManager.LayoutParams.TYPE_APPLICATION;
        lpIndicator.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

        lpIndicator.alpha = 1.0f;
        lpIndicator.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lpIndicator.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lpIndicator.format = PixelFormat.TRANSPARENT;
        lpIndicator.gravity = Gravity.LEFT | Gravity.TOP;

        lpContent = new WindowManager.LayoutParams();
        lpContent.type = WindowManager.LayoutParams.TYPE_APPLICATION;
        lpContent.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

        lpContent.alpha = 1.0f;
        lpContent.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lpContent.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lpContent.format = PixelFormat.TRANSPARENT;
        lpContent.gravity = Gravity.LEFT | Gravity.TOP;
    }

    private void initPosition() {
        switch (position) {
            case LEFT_TOP:
                lpIndicator.x = 0;
                lpIndicator.y = stateHeight + (floatViewContentHeight - floatViewIndicatorHeight)
                        / 2;

                lpContent.x = -floatViewContentWidth;
                lpContent.y = stateHeight;
                setSide(SIDE_LEFT);
                break;
            case LEFT_MID:
                lpIndicator.x = 0;
                lpIndicator.y = (screenHeight - floatViewIndicatorHeight) / 2;

                lpContent.x = -floatViewContentWidth;
                lpContent.y = (screenHeight - floatViewContentHeight) / 2;
                setSide(SIDE_LEFT);
                break;
            case LEFT_BOTTOM:
                lpIndicator.x = 0;
                lpIndicator.y = screenHeight - floatViewIndicatorHeight / 2
                        - floatViewContentHeight / 2;

                lpContent.x = -floatViewContentWidth;
                lpContent.y = screenHeight - floatViewContentHeight;
                setSide(SIDE_LEFT);
                break;
            case RIGHT_TOP:
                lpIndicator.x = screenWidth - floatViewIndicatorWidth;
                lpIndicator.y = stateHeight + (floatViewContentHeight - floatViewIndicatorHeight)
                        / 2;

                lpContent.x = screenWidth;
                lpContent.y = stateHeight;
                setSide(SIDE_RIGHT);
                break;
            case RIGHT_MID:
                lpIndicator.x = screenWidth - floatViewIndicatorWidth;
                lpIndicator.y = (screenHeight - floatViewIndicatorHeight) / 2;

                lpContent.x = screenWidth;
                lpContent.y = (screenHeight - floatViewContentHeight) / 2;
                setSide(SIDE_RIGHT);
                break;
            case RIGHT_BOTTOM:
                lpIndicator.x = screenWidth - floatViewIndicatorWidth;
                lpIndicator.y = screenHeight - floatViewIndicatorHeight / 2
                        - floatViewContentHeight / 2;

                lpContent.x = screenWidth;
                lpContent.y = screenHeight - floatViewContentHeight;
                setSide(SIDE_RIGHT);
                break;
            default:
                // 默认左中
                lpIndicator.x = 0;
                lpIndicator.y = (screenHeight - floatViewIndicatorHeight) / 2;

                lpContent.x = -floatViewContentWidth;
                lpContent.y = (screenHeight - floatViewContentHeight) / 2;
                setSide(SIDE_LEFT);
                break;
        }
    }

    // 悬浮按钮触摸监听器
    OnTouchListener indicatorTouchListener = new OnTouchListener() {
        private boolean isMoving = false;

        private int startX, startY;

        private int rawStartX, rawStartY;

        @Override
        public boolean onTouch(View v, MotionEvent ev) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    startX = (int) ev.getX();
                    startY = (int) ev.getY();
                    rawStartX = (int) ev.getRawX();
                    rawStartY = (int) ev.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (Math.abs(ev.getRawX() - rawStartX) > touchSlop
                            || Math.abs(ev.getRawY() - rawStartY) > touchSlop) {
                        isMoving = true;

                        // 计算悬浮窗图标的坐标
                        lpIndicator.x = (int) (ev.getRawX() - startX);
                        lpIndicator.y = (int) (ev.getRawY() - startY);

                        // 计算悬浮窗图标显示的边界
                        if (lpIndicator.y < stateHeight) {
                            lpIndicator.y = stateHeight;
                        } else if (lpIndicator.y > screenHeight - stateHeight
                                - floatViewIndicatorHeight) {
                            lpIndicator.y = screenHeight - stateHeight - floatViewIndicatorHeight;
                        }

                        boolean left = lpIndicator.x <= (screenWidth - floatViewIndicatorWidth) / 2;
                        setSide(left ? SIDE_LEFT : SIDE_RIGHT);
                        // 刷新悬浮窗的坐标
                        updateFloatViewContentPosition();
                        // 刷新悬浮窗的背景
                        setFloatViewIndicatorBackground();
                        setFloatViewContentBackground();
                        updateFloatView();
                    } else {
                        isMoving = false;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (!isMoving) {
                        handleClickFloatView();
                    } else {
                        closeFloatViewNoAnimate();
                        isMoving = false;
                    }
                    break;
            }
            return true;
        }
    };

    private void handleClickFloatView() {
        if (expand) {
            closeFloatView();
        } else {
            openFloatView();
        }
    }

    public void closeFloatView() {
        if (Build.VERSION.SDK_INT < 11) {
            closeFloatViewNoAnimate();
        } else {
            closeFloatViewWithAnimate();
        }
    }

    private void openFloatView() {
        if (Build.VERSION.SDK_INT < 11) {
            openFloatViewNoAnimate();
        } else {
            openFloatViewWithAnimate();
        }
    }

    /** 刷新悬浮窗角标背景 */
    public void setFloatViewIndicatorBackground() {
        switch (side) {
            case SIDE_LEFT:
                if (adapter != null && adapter.needShowRedPoint()) {
                    if (expand) {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_shine_right);
                    } else {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_shine_left);
                    }
                } else {
                    if (expand) {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_nomal_right);
                    } else {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_nomal_left);
                    }
                }
                break;
            case SIDE_RIGHT:
                if (adapter != null && adapter.needShowRedPoint()) {
                    if (expand) {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_shine_left);
                    } else {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_shine_right);
                    }
                } else {
                    if (expand) {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_nomal_left);
                    } else {
                        floatViewIndicatorImage
                                .setImageResource(Rx.drawable.kg_floatview_indicator_nomal_right);
                    }
                }
                break;
        }
    }

    /** 刷新悬浮窗内容背景 */
    private void setFloatViewContentBackground() {
        switch (side) {
            case SIDE_LEFT:
                floatViewContentGrid
                        .setBackgroundResource(Rx.drawable.kg_floatview_content_bg_left);
                break;
            case SIDE_RIGHT:
                floatViewContentGrid
                        .setBackgroundResource(Rx.drawable.kg_floatview_content_bg_right);
                break;
        }
    }

    /** 设置悬浮窗左右边 */
    private void setSide(int side) {
        this.side = side;
    }

    /** 悬浮窗是否展开 */
    boolean expand;

    private void setExpand(boolean expand) {
        this.expand = expand;
    }

    /** 展开悬浮窗 */
    private void openFloatViewNoAnimate() {
        switch (side) {
            case SIDE_LEFT:
                lpIndicator.x = floatViewContentWidth;
                lpContent.x = 0;
                break;
            case SIDE_RIGHT:
                lpIndicator.x = screenWidth - floatViewIndicatorWidth - floatViewContentWidth;
                lpContent.x = screenWidth - floatViewContentWidth;
                break;
        }

        // 计算悬浮窗的显示临界位置
        if (lpIndicator.y < stateHeight + floatViewContentHeight / 2 - floatViewIndicatorHeight / 2) {
            lpIndicator.y = stateHeight + floatViewContentHeight / 2 - floatViewIndicatorHeight / 2;
        } else if (lpIndicator.y > screenHeight - stateHeight - floatViewContentHeight / 2
                - floatViewIndicatorHeight / 2) {
            lpIndicator.y = screenHeight - stateHeight - floatViewContentHeight / 2
                    - floatViewIndicatorHeight / 2;
        }
        setExpand(true);
        floatViewContentLayout.setVisibility(View.VISIBLE);
        floatViewIndicatorLabel.setVisibility(View.GONE);

        updateFloatViewContentPosition();
        updateFloatView();
        setFloatViewIndicatorBackground();
    }

    @SuppressLint("NewApi")
    private void openFloatViewWithAnimate() {
        // Log.i("dax", "animateOpenFloatView");
        floatViewContentLayout.setVisibility(View.VISIBLE);
        floatViewIndicatorLabel.setVisibility(View.GONE);
        setExpand(true);
        setFloatViewIndicatorBackground();

        ArrayList<ValueAnimator> animators = new ArrayList<ValueAnimator>();
        ValueAnimator animOpenIndicator = null;
        ValueAnimator animOpenContent = null;
        switch (side) {
            case SIDE_LEFT:
                animOpenIndicator = ValueAnimator.ofInt(0, floatViewContentWidth);
                animOpenContent = ValueAnimator.ofInt(-floatViewContentWidth, 0);
                break;
            case SIDE_RIGHT:
                animOpenIndicator = ValueAnimator.ofInt(screenWidth - floatViewIndicatorWidth,
                        screenWidth - floatViewIndicatorWidth - floatViewContentWidth);
                animOpenContent = ValueAnimator.ofInt(screenWidth, screenWidth
                        - floatViewContentWidth);
                break;
        }

        animOpenIndicator.setRepeatCount(0);
        animOpenIndicator.setInterpolator(new LinearInterpolator());
        animOpenIndicator.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator anim) {
                lpIndicator.x = (Integer) anim.getAnimatedValue();
                updateFloatViewIndicator();
            }
        });
        animators.add(animOpenIndicator);
        animOpenContent.setRepeatCount(0);
        animOpenContent.setInterpolator(new LinearInterpolator());
        animOpenContent.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator anim) {
                lpContent.x = (Integer) anim.getAnimatedValue();
                updateFloatViewContent();
            }
        });
        animators.add(animOpenContent);
        ValueAnimator[] valueAnimators = animators.toArray(new ValueAnimator[animators.size()]);
        AnimatorSet animSet = new AnimatorSet();
        animSet.addListener(new FloatViewAnimListener());
        animSet.playTogether(valueAnimators);
        animSet.setDuration(400);
        animSet.start();
    }

    /** 更新悬浮窗内容的坐标 */
    private void updateFloatViewContentPosition() {
        switch (side) {
            case SIDE_LEFT:
                lpContent.x = lpIndicator.x - floatViewContentWidth;
                lpContent.y = lpIndicator.y - floatViewContentHeight / 2 + floatViewIndicatorHeight
                        / 2;
                break;
            case SIDE_RIGHT:
                lpContent.x = lpIndicator.x + floatViewIndicatorWidth;
                lpContent.y = lpIndicator.y - floatViewContentHeight / 2 + floatViewIndicatorHeight
                        / 2;
                break;
        }
    }

    /** 收拢悬浮窗 */
    private void closeFloatViewNoAnimate() {
        switch (side) {
            case SIDE_LEFT:
                lpIndicator.x = 0;
                lpContent.x = -floatViewContentWidth;
                break;
            case SIDE_RIGHT:
                lpIndicator.x = screenWidth - floatViewIndicatorWidth;
                lpContent.x = screenWidth;
                break;
        }
        setExpand(false);
        setFloatViewIndicatorBackground();
        updateFloatView();
        floatViewContentLayout.setVisibility(View.GONE);
    }

    @SuppressLint("NewApi")
    private void closeFloatViewWithAnimate() {
        // Log.i("dax", "animateCloseFloatView");
        setExpand(false);
        setFloatViewIndicatorBackground();

        ArrayList<ValueAnimator> animators = new ArrayList<ValueAnimator>();
        ValueAnimator animCloseIndicator = null;
        ValueAnimator animCloseContent = null;
        switch (side) {
            case SIDE_LEFT:
                animCloseIndicator = ValueAnimator.ofInt(floatViewContentWidth, 0);
                animCloseContent = ValueAnimator.ofInt(0, -floatViewContentWidth);
                break;
            case SIDE_RIGHT:
                animCloseIndicator = ValueAnimator.ofInt(screenWidth - floatViewIndicatorWidth
                        - floatViewContentWidth, screenWidth - floatViewIndicatorWidth);
                animCloseContent = ValueAnimator.ofInt(screenWidth - floatViewContentWidth,
                        screenWidth);
                break;
        }

        animCloseIndicator.setRepeatCount(0);
        animCloseIndicator.setInterpolator(new LinearInterpolator());
        animCloseIndicator.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator anim) {
                lpIndicator.x = (Integer) anim.getAnimatedValue();
                updateFloatViewIndicator();
            }
        });
        animators.add(animCloseIndicator);
        animCloseContent.setRepeatCount(0);
        animCloseContent.setInterpolator(new LinearInterpolator());
        animCloseContent.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator anim) {
                lpContent.x = (Integer) anim.getAnimatedValue();
                updateFloatViewContent();
                if (lpContent.x == -floatViewContentWidth || lpContent.x == screenWidth) {
                    floatViewContentLayout.setVisibility(View.GONE);
                }
            }
        });
        animators.add(animCloseContent);

        ValueAnimator[] valueAnimators = animators.toArray(new ValueAnimator[animators.size()]);
        AnimatorSet animSet = new AnimatorSet();
        animSet.addListener(new FloatViewAnimListener());
        animSet.playTogether(valueAnimators);
        animSet.setDuration(400);
        animSet.start();
    }

    private void updateFloatView() {
        try {
            if (isAdd) {
                wm.updateViewLayout(floatViewIndicatorLayout, lpIndicator);
                wm.updateViewLayout(floatViewContentLayout, lpContent);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void updateFloatViewIndicator() {
        try {
            if (isAdd) {
                wm.updateViewLayout(floatViewIndicatorLayout, lpIndicator);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void updateFloatViewContent() {
        try {
            if (isAdd) {
                wm.updateViewLayout(floatViewContentLayout, lpContent);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** 显示悬浮窗 */
    public synchronized void show() {
        try {
            if (!isAdd) {
                wm.addView(floatViewContentLayout, lpContent);
                wm.addView(floatViewIndicatorLayout, lpIndicator);
                isAdd = true;

                adapter.setFloatView(fv);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** 隐藏悬浮窗 */
    public synchronized void hide() {
        try {
            if (wm != null && floatViewIndicatorLayout != null && floatViewContentLayout != null
                    && isAdd) {
                wm.removeView(floatViewIndicatorLayout);
                wm.removeView(floatViewContentLayout);
                isAdd = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** 销毁悬浮窗 */
    public void release() {
        try {
            if (receiver != null) {
                context.unregisterReceiver(receiver);
                receiver = null;
            }

            if (animSetBreathe != null) {
                animSetBreathe.cancel();
                animSetBreathe = null;
            }

            if (floatViewContentGrid.getAnimation() != null) {
                floatViewContentGrid.getAnimation().cancel();
            }
            if (floatViewIndicatorImage.getAnimation() != null) {
                floatViewIndicatorImage.getAnimation().cancel();
            }

            if (wm != null && floatViewIndicatorLayout != null && floatViewContentLayout != null) {
                if (isAdd) {
                    wm.removeView(floatViewIndicatorLayout);
                    wm.removeView(floatViewContentLayout);
                }
                isAdd = false;
            }

            if (loader != null) {
                loader.clearCache();
                loader = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            fv = null;
        }
    }

    /**
     * 描述:悬浮窗广播接收器
     *
     * @author jerryliu
     * @since 2016年1月18日 上午10:51:40
     */
    class FloatViewReceiver extends BaseBroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
            String action = intent.getAction();
            if (SDKActions.ACTION_UPDATE_TOOLBAR_AFTER_LOGIN_SUCCESS.equals(action)) {
                if (adapter != null) {
                    User user = UserManager.getInstance().getCurrentUserInternal();
                    // 如果有未读消息，用户中心显示红点提示
                    if (!adapter.showActivityTag
                            && user != null
                            && user.getUnreadmails() > 0
                            && !user.isUnreadMailReminded()
                            && !adapter.containsRedPoint(String
                                    .valueOf(FloatViewContentAdapter.INDEX_USERCENTER))) {
                        adapter.addShowRedPoint(String
                                .valueOf(FloatViewContentAdapter.INDEX_USERCENTER));
                    }

                    // 显示游戏中心红点
                    if (user != null
                            && user.isGameCenterNeedRedPointRemind()
                            && adapter.isVisible(FloatViewContentAdapter.INDEX_GAMECENTER)
                            && !adapter.containsRedPoint(String
                                    .valueOf(FloatViewContentAdapter.INDEX_GAMECENTER))) {
                        adapter.addShowRedPoint(String
                                .valueOf(FloatViewContentAdapter.INDEX_GAMECENTER));
                    }

                    adapter.notifyDataSetChanged();
                    setFloatViewIndicatorBackground();
                }
            } else if (SDKActions.ACTION_SET_LOGIN_PSD_SUCCESS.equals(action)) {
                User user = UserManager.getInstance().getCurrentUserInternal();
                // 设置密码成功后，隐藏补填密码入口
                setSetPsdGone();
                // 补填密码后，检查用户中心的红点显示
                if (!adapter.showActivityTag
                        && user != null
                        && user.getUnreadmails() > 0
                        && !adapter.containsRedPoint(String
                                .valueOf(FloatViewContentAdapter.INDEX_USERCENTER))) {
                    adapter.addShowRedPoint(String
                            .valueOf(FloatViewContentAdapter.INDEX_USERCENTER));
                }
                //
            } else if (SDKActions.ACTION_CHANGE_TO_VIP.equals(action)) {
                // 充值成功成为VIP，显示VIP入口
                setVipVisible();
            } else if (SDKActions.ACTION_UNREAD_EMAIL_CLICKED.equals(action)) {
                // 设置当前新邮件已经提醒，可以取消红点了
                if (adapter.containsRedPoint(String
                        .valueOf(FloatViewContentAdapter.INDEX_USERCENTER))) {
                    adapter.removeShowRedPoint(String
                            .valueOf(FloatViewContentAdapter.INDEX_USERCENTER));
                    adapter.notifyDataSetChanged();
                    setFloatViewIndicatorBackground();
                }
            } else if (SDKActions.ACTION_STATE_HAS_GIFTBAG.equals(action)) {
                setGiftBagVisible();
            }
        }
    }

    /** 隐藏补填密码入口 */
    public void setSetPsdGone() {
        if (adapter != null) {
            adapter.removeData(FloatViewContentAdapter.INDEX_SETPSD);
            adapter.notifyDataSetChanged();
        }
    }

    /** 刷新悬浮窗图标的布局 */
    public void updateFloatViewIndicatorLayout() {
        ViewTreeObserver contentObserver = floatViewIndicatorLayout.getViewTreeObserver();
        contentObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (floatViewIndicatorLayout == null) {
                    return;
                }
                if (Build.VERSION.SDK_INT <= 15) {
                    floatViewIndicatorLayout.getViewTreeObserver().removeGlobalOnLayoutListener(
                            this);
                } else {
                    floatViewIndicatorLayout.getViewTreeObserver().removeOnGlobalLayoutListener(
                            this);
                }
                floatViewIndicatorWidth = floatViewIndicatorLayout.getWidth();
                floatViewIndicatorHeight = floatViewIndicatorLayout.getHeight();
            }
        });
    }

    AnimatorSet animSetBreathe;

    public void startBreatheAnimation() {
        if (Build.VERSION.SDK_INT < 11) {
            return;
        }

        if (floatViewIndicatorImage != null) {
            floatViewIndicatorImage.setDrawingCacheEnabled(false);
            if (animSetBreathe != null && animSetBreathe.isRunning()) {
                return;
            }
            ObjectAnimator scaleAnimationx = ObjectAnimator.ofFloat(floatViewIndicatorImage,
                    "scaleX", 1.0f, 0.95f);
            scaleAnimationx.setRepeatCount(Animation.INFINITE);
            scaleAnimationx.setRepeatMode(Animation.REVERSE);
            ObjectAnimator scaleAnimationy = ObjectAnimator.ofFloat(floatViewIndicatorImage,
                    "scaleY", 1.0f, 0.95f);
            scaleAnimationy.setRepeatCount(Animation.INFINITE);
            scaleAnimationy.setRepeatMode(Animation.REVERSE);
            ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(floatViewIndicatorImage,
                    "alpha", 1.0f, 0.6f);
            alphaAnimation.setRepeatCount(Animation.INFINITE);
            alphaAnimation.setRepeatMode(Animation.REVERSE);
            animSetBreathe = new AnimatorSet();
            animSetBreathe.setDuration(800);
            animSetBreathe.playTogether(scaleAnimationx, scaleAnimationy, alphaAnimation);
            animSetBreathe.start();
        }
    }

    public void removeBreatheAnimation() {
        if (Build.VERSION.SDK_INT < 11) {
            return;
        }
        if (animSetBreathe != null) {
            animSetBreathe.cancel();
            animSetBreathe = null;
        }
    }

    /** 悬浮窗动画监听 */
    class FloatViewAnimListener implements AnimatorListener {
        // 是否在显示呼吸灯
        private boolean runningBreathe = false;

        @Override
        public void onAnimationStart(Animator animation) {
            if (animSetBreathe != null && animSetBreathe.isRunning()) {
                runningBreathe = true;
                removeBreatheAnimation();
            }
        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            if (runningBreathe) {
                startBreatheAnimation();
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }
    }

    public static void createAndSendUpdateIntent(Context context, String action) {
        Intent intent = new Intent(action);
        context.sendBroadcast(intent);
    }
}
